import Axios from 'axios'
import printf from 'printf'

const cread = require('cread');

const DEBUG = false

main()

const FORMAT = '%-10s%-40s%-30s'

const CMD_REFRESH = ':rs'
const CMD_EXIT = ':q'

async function main() {
  const host = "192.168.0.103"
  const port = 8500

  while (true) {
    const info = await loadInfo(host, port)
    const commands: string[] = [CMD_REFRESH, CMD_EXIT].concat(info.commands)

    printServices(info.list)
    console.log('-------------')
    printHelp()

    const cmd = await interactive(commands)
    if (isNaN(Number(cmd))) {
      switch (cmd) {
        case CMD_EXIT: {
          return
        }
      }
    } else {
      const service = info.list[Number(cmd)]
      await deregister(service.ID, host, port)
      await readAny("移除成功，按回车继续")
    }
  }
}

async function loadInfo(host: string = "localhost", port: number = 8500): Promise<Info> {
  const {data} = await Axios.get(`http://${host}:${port}/v1/agent/services`);
  console.log(data)
  const commands: string[] = []
  const list = []
  let idx = 0
  for (const key in data) {
    list[idx] = data[key]
    commands.unshift(idx.toString())
    idx++
  }
  return {commands, list}
}

function printServices(services: Service[]) {
  if (DEBUG) {
    console.log("=== debug ===")
  } else {
    console.clear()
  }
  console.log(printf(FORMAT, "ID", "Service", "Address"))
  for (let i = 0; i < services.length; i++) {
    const service = services[i]
    console.log(printf(FORMAT, i, service.ID, `${service.Address}:${service.Port}`))
  }
}

function printHelp() {
  const fmt = '%-10s%s'
  console.log(printf(fmt, CMD_REFRESH, "刷新列表"))
  console.log(printf(fmt, CMD_EXIT, "退出"))
}

async function interactive(commands: (string | number)[]): Promise<string> {
  while (true) {
    const answer = await read('请输入要移除的服务(ID)：', commands)
    if (!isNaN(answer)) {
      const confirm = await read('　　　　　　　再次输入：', commands)
      if (confirm !== answer) {
        console.log("输入不一致")
      }
    }
    return answer
  }
}

async function read(prompt: string, commands: (string | number)[]) {
  return await cread.line({
    prompt,
    pattern: function (input: string) {
      return commands.findIndex(value => value === input) >= 0
    },
    retry: Number.POSITIVE_INFINITY
  })
}

async function readAny(prompt: string) {
  return await cread.line({
    prompt,
    pattern: /.*/
  })
}

async function deregister(serviceId: string, host: string = "localhost", port: number = 8500): Promise<boolean> {
  if (DEBUG) {
    console.log(`(DEBUG) 移除 ${serviceId}`)
  }
  if (!DEBUG && serviceId) {
    console.log(`正在移除 ${serviceId} ...`)
    await Axios.put(`http://${host}:${port}/v1/agent/service/deregister/${serviceId}`)
    return true
  }
  return false
}

interface Info {
  commands: string[],
  list: Service[]
}

interface Service {
  ID: string,
  Service: string,
  Tags: string[],
  Meta: object,
  Port: number,
  Address: string,
  TaggedAddresses: object,
  Weights: { Passing: number, Warning: number },
  EnableTagOverride: boolean
}
